package com.geek.factory.aop;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.geek.factory.annotation.BizLogRecord;
import com.geek.factory.entity.BizLog;
import com.geek.factory.result.Result;
import com.geek.factory.service.IBizLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Map;

@Aspect
@Component
@Slf4j
public class BizLogAspect {

    @Autowired
    private IBizLogService bizLogService;

    // Jackson序列化工具，用于参数/返回值转JSON
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Around("@annotation(bizLogRecord)")
    public Object logOperation(ProceedingJoinPoint joinPoint, BizLogRecord bizLogRecord) throws Throwable {
        long startTime = System.currentTimeMillis();

        // 获取方法信息
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String methodName = method.getDeclaringClass().getSimpleName() + "." + method.getName();

        // 获取请求信息
        String ipAddress = getIpAddress();
        String userAgent = getUserAgent();

        // 获取操作人信息
        String operator = getCurrentUser(joinPoint.getArgs());

        // 获取注解信息
        String action = bizLogRecord.value();
        String description = bizLogRecord.description();
        boolean logParams = bizLogRecord.logParams();
        boolean logResult = bizLogRecord.logResult();

        // 记录参数
        String paramsJson = null;
        if (logParams) {
            try {
                paramsJson = objectMapper.writeValueAsString(joinPoint.getArgs());
                
                // 限制参数长度，避免数据库字段过长
                if (paramsJson != null && paramsJson.length() > 4000) {
                    paramsJson = paramsJson.substring(0, 4000) + "...[截断]";
                    log.warn("参数过长，已截断。原始长度: {}", paramsJson.length());
                }
            } catch (Exception e) {
                log.warn("序列化参数失败: {}", e.getMessage());
                paramsJson = Arrays.toString(joinPoint.getArgs());
            }
        }

        Object result = null;
        String resultJson = null;
        boolean success = true;
        String errorMessage = null;

        try {
            // 执行原方法
            result = joinPoint.proceed();

            // 记录返回值
            if (logResult && result != null) {
                try {
                    resultJson = objectMapper.writeValueAsString(result);
                } catch (Exception e) {
                    log.warn("序列化返回值失败: {}", e.getMessage());
                    resultJson = result.toString();
                }
            }

            // 判断业务逻辑是否成功
            success = isBusinessSuccess(result);
            
            // 如果业务逻辑失败，从Result中获取错误信息
            if (!success && result instanceof Result) {
                Result resultObj = (Result) result;
                errorMessage = resultObj.getMsg(); // 获取Result中的错误消息
            }

            return result;
        } catch (Exception e) {
            success = false;
            errorMessage = e.getMessage();
            throw e;
        } finally {
            // 计算执行时间
            long endTime = System.currentTimeMillis();
            long timeCost = endTime - startTime;

            // 保存日志
            try {
                BizLog logEntity = new BizLog();
                logEntity.setOperator(operator);
                logEntity.setAction(action);
                logEntity.setDescription(description);
                logEntity.setMethod(methodName);
                logEntity.setParams(paramsJson);
                logEntity.setResult(resultJson);
                logEntity.setTimeCostMs((int) timeCost);
                logEntity.setIpAddress(ipAddress);
                logEntity.setUserAgent(userAgent);
                logEntity.setSuccess(success);
                logEntity.setErrorMessage(errorMessage);
                logEntity.setCreateTime(LocalDateTime.now());

                bizLogService.save(logEntity);
            } catch (Exception e) {
                log.error("保存操作日志失败: {}", e.getMessage(), e);
            }
        }
    }

    /**
     * 获取当前登录用户
     */
    private String getCurrentUser(Object[] args) {
        try {
            // 从请求参数中获取操作人信息
            for (Object arg : args) {
                if (arg instanceof Map) {
                    Map<String, Object> map = (Map<String, Object>) arg;
                    if (map.containsKey("operator")) {
                        return String.valueOf(map.get("operator"));
                    }
                }
            }
            
            // 如果参数中没有操作人，尝试从Session或Token中获取
            // 这里可以根据你的认证框架来实现
            return "system";
        } catch (Exception e) {
            return "unknown";
        }
    }

    /**
     * 判断业务逻辑是否成功
     */
    private boolean isBusinessSuccess(Object result) {
        try {
            if (result instanceof Result) {
                Result resultObj = (Result) result;
                // 根据Result类的success字段来判断
                return resultObj.isSuccess();
            }
            return true; // 如果不是Result类型，默认认为成功
        } catch (Exception e) {
            log.warn("判断业务成功状态失败: {}", e.getMessage());
            return true;
        }
    }

    /**
     * 获取IP地址
     */
    private String getIpAddress() {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                String ip = request.getHeader("X-Forwarded-For");
                if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("Proxy-Client-IP");
                }
                if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("WL-Proxy-Client-IP");
                }
                if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("HTTP_CLIENT_IP");
                }
                if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("HTTP_X_FORWARDED_FOR");
                }
                if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getRemoteAddr();
                }
                
                // 处理IPv6的localhost地址
                if ("0:0:0:0:0:0:0:1".equals(ip) || "::1".equals(ip)) {
                    return "127.0.0.1";
                }
                
                return ip;
            }
        } catch (Exception e) {
            log.warn("获取IP地址失败: {}", e.getMessage());
        }
        return "unknown";
    }

    /**
     * 获取User-Agent
     */
    private String getUserAgent() {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                return request.getHeader("User-Agent");
            }
        } catch (Exception e) {
            log.warn("获取User-Agent失败: {}", e.getMessage());
        }
        return "unknown";
    }
}